package service

import (
	"context"
	"github.com/pkg/errors"
	"gorm.io/gorm"
	"mall/api/bilinadmin"
	"mall/api/mall"
	"mall/internal/constant"
	"mall/internal/model"
	"mall/pkg/ecode"
	"mall/pkg/orm"
	"mall/pkg/util"
)

// 开通商城
func (s *Service) CreateMall(ctx context.Context, req *mall.CreateMallConfigRequest) (
	resp *mall.DefaultResp, err error) {
	if _, ok := bilinadmin.BizTypeEnum_value[req.OperationMode]; !ok {
		err = ecode.BadRequest("运营模式枚举不合法")
		return
	}
	if err = s.downstream.CheckAdmin(ctx, req.Token, 0); err != nil {
		return
	}
	if err = s.dao.Transaction(ctx, func(ctx context.Context) (err error) {
		if _, err = s.dao.GetConfig(ctx, req.Token.SgId); err != nil {
			if errors.Cause(err) != gorm.ErrRecordNotFound {
				return
			}
		} else {
			// 商城已经开通，不允许重复操作
			err = ecode.AppendMessage(constant.ErrNeedRefresh, "商城已经开通，无需重复操作")
			return
		}
		if err = s.dao.Create(ctx, &model.Config{
			SgId:              req.Token.SgId,
			OperationMode:     uint8(bilinadmin.BizTypeEnum_value[req.OperationMode]),
			AllowBooking:      req.AllowBooking,
			BookingDays:       req.BookingDays,
			AutoConfirmedDays: req.AutoConfirmedDays,
			RefundAllowedDays: req.RefundAllowedDays,
			InventoryMode:     uint8(req.InventoryMode),
			StoreIds:          orm.IntArray{}, // 创建时无法创建任何店铺，故无需处理
			Operator:          req.Token.EmpId,
		}); err != nil {
			return
		}
		if err = s.downstream.NotifyOpenMall(ctx, req.OperationMode, req.Token.SgId, req.Token.EmpId); err != nil {
			return
		}
		return
	}); err != nil {
		return
	}
	resp = &mall.DefaultResp{Status: true}
	return
}

// 查看商城配置
func (s *Service) GetMallConfig(ctx context.Context, req *mall.CommonRequest) (
	resp *mall.GetMallConfigResp, err error) {
	if err = s.downstream.CheckMallPermission(ctx, req.Token, req.PStoreId); err != nil {
		return
	}
	var (
		config *model.Config
		stores []*mall.StoreSimpleView
	)
	if config, err = s.dao.GetConfig(ctx, req.Token.SgId); err != nil {
		if errors.Cause(err) == gorm.ErrRecordNotFound {
			err = ecode.AppendMessage(constant.ErrNeedRefresh, "商城尚未开通，无法获取配置")
			return
		}
		return
	}
	if len(config.StoreIds) != 0 {
		if req.PStoreId != 0 {
			for _, storeId := range config.StoreIds {
				if storeId == int(req.PStoreId) {
					if stores, err = s.downstream.GetStoreListByStoreIds(ctx, []int{storeId}); err != nil {
						return
					}
				}
			}
		} else {
			if stores, err = s.downstream.GetStoreListByStoreIds(ctx, config.StoreIds); err != nil {
				return
			}
		}
	}
	resp = &mall.GetMallConfigResp{
		OperationMode:     bilinadmin.BizTypeEnum_name[int32(config.OperationMode)],
		AllowBooking:      config.AllowBooking,
		BookingDays:       config.BookingDays,
		AutoConfirmedDays: config.AutoConfirmedDays,
		RefundAllowedDays: config.RefundAllowedDays,
		InventoryMode:     mall.InventoryMode(config.InventoryMode),
		Stores:            stores,
	}
	return
}

// 商城配置修改
func (s *Service) UpdateMall(ctx context.Context, req *mall.UpdateMallConfigRequest) (
	resp *mall.DefaultResp, err error) {
	if err = s.downstream.CheckAdmin(ctx, req.Token, 0); err != nil {
		return
	}
	if err = s.dao.Transaction(ctx, func(ctx context.Context) (err error) {
		var (
			config   *model.Config
			storeIds []int
			stores   []*mall.StoreSimpleView
		)
		if config, err = s.dao.GetConfig(ctx, req.Token.SgId); err != nil {
			if errors.Cause(err) == gorm.ErrRecordNotFound {
				err = ecode.AppendMessage(constant.ErrNeedRefresh, "商城尚未开通，无法编辑配置")
				return
			}
			return
		}
		if len(req.StoreIds) != 0 {
			for _, storeId := range req.StoreIds {
				storeIds = append(storeIds, int(storeId))
			}
			if stores, err = s.downstream.GetStoreListByStoreIds(ctx, storeIds); err != nil {
				return
			}
			if len(stores) != len(storeIds) {
				err = ecode.AppendMessage(constant.ErrNeedRefresh, "所选门店包含已删除门店，请刷新页面重新关联")
			}
		}
		config.AllowBooking = req.AllowBooking
		config.BookingDays = req.BookingDays
		config.AutoConfirmedDays = req.AutoConfirmedDays
		config.RefundAllowedDays = req.RefundAllowedDays
		config.InventoryMode = uint8(req.InventoryMode)
		config.StoreIds = storeIds
		config.Operator = req.Token.EmpId
		if err = s.dao.Save(ctx, config); err != nil {
			return
		}
		return
	}); err != nil {
		return
	}
	resp = &mall.DefaultResp{Status: true}
	return
}

func getCustomPrice(sku *model.ShelfSku) (price uint64) {
	if sku.IsCustomized {
		price = sku.CustomPrice
	} else {
		price = sku.SyncPrice
	}
	return
}

func getCustomName(prod *model.ShelfProd) (name string) {
	if prod.CustomName != "" {
		name = prod.CustomName
	} else {
		name = prod.SyncName
	}
	return
}

func getPriceRangeDict(skus []*model.ShelfSku) (priceRangeDict map[uint64][]uint64) {
	priceRangeDict = make(map[uint64][]uint64)
	for _, sku := range skus {
		price := getCustomPrice(sku)
		if skuPrice, ok := priceRangeDict[sku.ProdId]; !ok {
			priceRangeDict[sku.ProdId] = []uint64{price, price}
		} else if skuPrice[0] > price {
			priceRangeDict[sku.ProdId][0] = price
		} else if skuPrice[1] < price {
			priceRangeDict[sku.ProdId][1] = price
		}
	}
	return
}

// 查看商城装修
func (s *Service) GetMallDecoration(ctx context.Context, req *mall.GetMallDecorationRequest) (
	resp *mall.GetMallDecorationResp, err error) {
	if err = s.downstream.CheckMallPermission(ctx, req.Token, req.PStoreId); err != nil {
		return
	}
	var (
		decoration *model.Decoration
		prods      []*model.ShelfProd
		skus       []*model.ShelfSku
	)
	if decoration, err = s.dao.GetDecoration(
		ctx, req.Token.SgId, req.PStoreId, uint8(req.SourceType)); err != nil {
		if errors.Cause(err) == gorm.ErrRecordNotFound {
			err = nil
			var config *model.Config
			if config, err = s.dao.GetConfig(ctx, req.Token.SgId); err != nil {
				if errors.Cause(err) == gorm.ErrRecordNotFound {
					err = ecode.AppendMessage(constant.ErrNeedRefresh, "商城尚未开通，无法编辑配置")
					return
				}
				return
			}
			resp = &mall.GetMallDecorationResp{
				Prods: make([]*mall.SimpleMallProdView, 0),
			}
			if resp.DecorationInfo, err = s.dao.GetDecorationTemplate(
				ctx, config.OperationMode, req.PStoreId == 0); err != nil {
				return
			}
			return
		}
		return
	}
	resp = &mall.GetMallDecorationResp{
		DecorationInfo: decoration.Decoration,
		Prods:          make([]*mall.SimpleMallProdView, 0),
	}
	if len(decoration.ProdIds) != 0 {
		// 加载货架商品
		prodIds := util.FormatIntArrayToInt64Array(decoration.ProdIds)
		if prods, err = s.dao.FindShelfProdsByProdIds(ctx, req.Token.SgId, req.PStoreId, prodIds); err != nil {
			return
		}
		if skus, err = s.dao.FindShelfSkusByProdIds(ctx, req.Token.SgId, req.PStoreId, prodIds); err != nil {
			return
		}
		priceRangeDict := getPriceRangeDict(skus)
		for _, p := range prods {
			resp.Prods = append(resp.Prods, &mall.SimpleMallProdView{
				Id:         p.ProdId,
				Name:       getCustomName(p),
				PriceRange: priceRangeDict[p.ProdId],
				TitlePic:   p.SyncPic,
			})
		}
	}
	return
}

// 修改商城装修
func (s *Service) UpdateMallDecoration(ctx context.Context, req *mall.UpdateMallDecorationRequest) (
	resp *mall.DefaultResp, err error) {
	if err = s.downstream.CheckMallPermission(ctx, req.Token, req.PStoreId); err != nil {
		return
	}
	if err = s.dao.Transaction(ctx, func(ctx context.Context) (err error) {
		// 前端要求prodId无需校验，目前整个模块不会触发刷新，因此允许不在货架的商品ID序列保存
		var decoration *model.Decoration
		if decoration, err = s.dao.GetDecoration(
			ctx, req.Token.SgId, req.PStoreId, uint8(req.SourceType)); err != nil {
			if errors.Cause(err) == gorm.ErrRecordNotFound {
				if err = s.dao.Create(ctx, &model.Decoration{
					SgId:       req.Token.SgId,
					PStoreId:   req.PStoreId,
					SourceType: uint8(req.SourceType),
					Decoration: orm.JSON(req.DecorationInfo),
					ProdIds:    util.FormatInt64ArrayToIntArray(req.ProdIds),
					Operator:   req.Token.EmpId,
				}); err != nil {
					return
				}
				return
			}
			return
		} else {
			decoration.Decoration = orm.JSON(req.DecorationInfo)
			decoration.ProdIds = util.FormatInt64ArrayToIntArray(req.ProdIds)
			decoration.Operator = req.Token.EmpId
			if err = s.dao.AutoUpdate(ctx, decoration); err != nil {
				return
			}
		}
		return
	}); err != nil {
		return
	}
	resp = &mall.DefaultResp{Status: true}
	return
}
